package com.sg.business.permission.ui.column;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.rap.rwt.scripting.ClientListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

import com.sg.business.permission.model.PermissionAction;
import com.sg.widgets.Widgets;

public abstract class AbstractDateColumn {
	
	private boolean isEditable;

	private static final String DATE_FORMART = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS";
	private static final String[] SDF_DATE_FORMARTS = new String[] {
			"yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss",
			"yyyy/MM/dd HH:mm:ss", "yy/M/d H:m:s", "yyyy-MM-dd", "yyyy/MM/dd",
			"yy/M/d" };

	public TableViewerColumn create(final TableViewer viewer) {
		TableViewerColumn column = new TableViewerColumn(viewer, SWT.CENTER);
		column.getColumn().setWidth(128);
		column.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Date date = getDate((PermissionAction) element);
				if (date != null) {
					return String.format(DATE_FORMART, date);
				} else {
					return "";
				}
			}

			@Override
			public Color getBackground(Object element) {
				if (!canEdit(viewer, (PermissionAction) element)) {
					return Widgets.getColor(viewer.getControl().getDisplay(),
							0xe9, 0xe9, 0xe9);
				}
				return super.getBackground(element);
			}
		});

		final CellEditor cellEditor = new TextCellEditor(viewer.getTable()) {
			@Override
			protected Control createControl(Composite parent) {
				Control control = super.createControl(parent);
				String scriptCode = getScript();
				ClientListener clientListener = new ClientListener(scriptCode);
				control.addListener(SWT.Verify, clientListener);
				control.addListener(SWT.Modify, clientListener);
				return control;
			}
		};
		column.setEditingSupport(new EditingSupport(viewer) {

			@Override
			protected void setValue(Object element, Object value) {
				Date date = null;
				if (value != null) {
					String sValue = value.toString();
					for (int i = 0; i < SDF_DATE_FORMARTS.length; i++) {
						try {
							SimpleDateFormat sdf = new SimpleDateFormat(
									SDF_DATE_FORMARTS[i]);
							date = sdf.parse(sValue);
							break;
						} catch (Exception e) {
						}
					}
				}
				AbstractDateColumn.this.setValue(viewer,
						(PermissionAction) element, date);
			}

			@Override
			protected Object getValue(Object element) {
				Date date = getDate((PermissionAction) element);
				if (date != null) {
					return String.format(DATE_FORMART, date);
				} else {
					return "";
				}
			}

			@Override
			protected CellEditor getCellEditor(Object element) {
				return cellEditor;
			}

			@Override
			protected boolean canEdit(Object element) {
				return AbstractDateColumn.this.canEdit(viewer,
						(PermissionAction) element);
			}
		});

		return column;
	}

	protected boolean canEdit(TableViewer viewer, PermissionAction action) {
		return isEditable()&&action.getActionDefinition().isEditable();
	}

	protected String getScript() {
		StringBuffer sb = new StringBuffer();
		sb.append("var handleEvent = function(event) {");
		sb.append("	switch (event.type) {");
		sb.append("	case SWT.Modify:");
		sb.append("		handleModifyEvent(event);");
		sb.append("		break;");
		sb.append("	case SWT.Verify:");
		sb.append("		handleVerifyEvent(event);");
		sb.append("		break;");
		sb.append("	}");
		sb.append("};");
		sb.append("var handleVerifyEvent = function(event) {");
		sb.append("	var input = event.text;");
		sb.append("	var text = event.widget.getText();");
		sb.append("	var start = event.start;");
		sb.append("	var end = event.end;");
		sb.append("	var left = text.slice(0, start);");
		sb.append("	var right = text.slice(end);");
		sb.append("	var result = left + input + right;");
		sb.append("	var p1 = result.split(\"-\").length - 1;");
		sb.append("	var p2 = result.split(\":\").length - 1;");
		sb.append("	if (input !== \"\") {");
		sb.append("		if (p1 == 0 && result.match(/\\d{4}/) !== null)");
		sb.append("			event.widget.setText(result + \"-\");");
		sb.append("		if (p1 == 1 && result.match(/\\d{4}\\-\\d{2}/) !== null)");
		sb.append("			event.widget.setText(result + \"-\");");
		sb.append("		if (p2 == 0 && result.match(/^\\d{4}\\-\\d{2}\\-\\d{2}\\ \\d{2}/) !== null)");
		sb.append("			event.widget.setText(result + \":\");");
		sb.append("		if (p2 == 1 && result.match(/^\\d{4}\\-\\d{2}\\-\\d{2}\\ \\d{2}\\:\\d{2}/) !== null)");
		sb.append("			event.widget.setText(result + \":\");");
		sb.append("	}");
		sb.append("};");
		sb.append("var handleModifyEvent = function(event) {");
		sb.append("	var text = event.widget.getText();");
		sb.append("	if (text === \"\"");
		sb.append("			|| text.match(/^\\d{4}\\-\\d{2}\\-\\d{2}$/) !== null");
		sb.append("			|| text.match(/^\\d{4}\\-\\d{2}\\-\\d{2}\\ \\d{2}\\:\\d{2}\\:\\d{2}$/) !== null)");
		sb.append("		event.widget.setBackground(null);");
		sb.append("	else");
		sb.append("		event.widget.setBackground([ 255, 128, 128 ]);");
		sb.append("};");
		return sb.toString();
	}

	protected void setValue(TableViewer viewer, PermissionAction element,
			Date date) {
		viewer.update(element, null);
	}

	protected abstract Date getDate(PermissionAction element);

	public boolean isEditable() {
		return isEditable;
	}

	public void setEditable(boolean isEditable) {
		this.isEditable = isEditable;
	}

}
